#pragma once

#include <windows.h>
#include <string>
#include <memory>

enum class CaptureMethod {
    GDI = 0,
    DXGI = 1,
    AUTO = 2
};

enum class CaptureResult {
    SUCCESS = 0,
    ERROR_INIT_FAILED = 1,
    ERROR_CAPTURE_FAILED = 2,
    ERROR_SAVE_FAILED = 3,
    ERROR_DESKTOP_SWITCH = 4
};

struct CaptureSettings {
    CaptureMethod method;
    std::string outputPath;
    int captureInterval;
    bool enableDesktopMonitoring;
    bool captureSecureDesktops;

    CaptureSettings() :
        method(CaptureMethod::AUTO),
        outputPath("C:\\ScreenCapture"),
        captureInterval(1000),
        enableDesktopMonitoring(true),
        captureSecureDesktops(true) {}
};

class GDICapture;
class DXGICapture;
class DesktopMonitor;
class BMPSaver;
class SecureDesktopCapture;
class SystemServiceCapture;

class ScreenCapture {
public:
    ScreenCapture();
    ~ScreenCapture();

    CaptureResult Initialize(const CaptureSettings& settings);
    CaptureResult StartCapture();
    CaptureResult StopCapture();
    CaptureResult CaptureFrame();

    bool IsCapturing() const { return m_isCapturing; }
    CaptureMethod GetActiveMethod() const { return m_activeMethod; }
    std::string GetLastError() const { return m_lastError; }

private:
    CaptureResult InitializeCaptureMethods();
    CaptureResult SwitchCaptureMethod(CaptureMethod method);
    CaptureResult HandleDesktopSwitch();
    std::string GenerateFilename() const;

    static DWORD WINAPI CaptureThreadProc(LPVOID lpParam);
    void CaptureLoop();

private:
    CaptureSettings m_settings;
    CaptureMethod m_activeMethod;
    bool m_isCapturing;
    bool m_shouldStop;
    std::string m_lastError;

    HANDLE m_captureThread;
    HANDLE m_stopEvent;

    std::unique_ptr<GDICapture> m_gdiCapture;
    std::unique_ptr<DXGICapture> m_dxgiCapture;
    std::unique_ptr<DesktopMonitor> m_desktopMonitor;
    std::unique_ptr<BMPSaver> m_bmpSaver;
    std::unique_ptr<SecureDesktopCapture> m_secureCapture;
    std::unique_ptr<SystemServiceCapture> m_systemServiceCapture;
};